import io

from PIL import Image
from typing import IO, Optional
from werkzeug.datastructures import FileStorage
from application.config.ServerConfig import ServerConfig
from application.mapper.ImageMapper import ImageMapper
from application.model.ImageModel import ImageModel
from application.util.FileUtil import verify_file_size
from application.util.StatusCode import StatusCode
from application.middleware.UploadMiddleware import *
from application.exception.BasicException import BasicException
from application.util.StringUtil import random_uuid


class ImageLogic:
    """
    图片逻辑层
    """
    @staticmethod
    def upload_image(image_storage: Optional[FileStorage]) -> Optional[dict]:
        """
        上传图片
        :param image_storage: 图片FileStorage对象
        :return: 图片信息
        """
        # 检查是否有文件
        if not image_storage:
            raise BasicException(status_code=StatusCode.BAD_REQUEST_ERROR.value, error_message="请上传图片")
        # 检查文件大小
        if not verify_file_size(file_obj=image_storage):
            error_message: str = f"图片大小不能超过{ServerConfig.file_max_size / 1024 / 1024}M"
            raise BasicException(status_code=StatusCode.FILE_SIZE_ERROR.value, error_message=error_message)
        # 重命名文件
        image_storage.filename = random_uuid() + "." + image_storage.filename.rsplit(".")[-1]
        # 获取图片IO对象
        image_io: IO = image_storage.stream
        # 获取图片字节流IO
        image_bytes: io.BytesIO = io.BytesIO()
        image_storage.save(image_bytes)
        # 检查图片格式
        try:
            Image.open(image_io)
        except IOError:
            raise BasicException(status_code=StatusCode.UNSUPPORTED_MEDIA_TYPE_ERROR.value,
                                 error_message="不是图片格式")
        # 上传图片
        files: list = [("file", (image_storage.filename, image_io, "image/*"))]  # 上传的文件对象列表
        response: dict = upload_image(files=files, file_bytes=image_bytes)
        # 获取图片信息
        unique_id: str = response.get("unique_id")  # 用于删除的ID
        url: str = response.get("url")
        image_id: str = random_uuid()  # 随机生成图片ID
        # 插入图片数据
        image_model: ImageModel = ImageModel(id=image_id, unique_id=unique_id, url=url)
        if not ImageMapper.insert(image_model=image_model):
            raise BasicException(status_code=StatusCode.ERROR.value, error_message="内部错误，请稍后再试")
        return {
            "unique_id": unique_id,
            "url": url,
            "id": image_id
        }

    @staticmethod
    def delete_image_by_id(image_id: str) -> None:
        """
        根据图片ID删除图片
        :param image_id: 图片ID
        :return:
        """
        # 检查参数完整性
        if not image_id:
            raise BasicException(status_code=StatusCode.BAD_REQUEST_ERROR.value, error_message="请完善参数")
        # 获取图片信息
        image_model_list: Optional[list] = ImageMapper.get_info_by_ids(image_ids=image_id)
        # 检查图片在不在库中
        if not image_model_list:
            return None
        # 获取图片对象
        image_model: ImageModel = image_model_list[0]
        # 删除图片
        delete_image(unique_id=image_model.unique_id)
        # 删除库中数据
        if not ImageMapper.delete_by_id(image_model=image_model):
            raise BasicException(status_code=StatusCode.ERROR.value, error_message="内部错误，请稍后再试")

    @staticmethod
    def get_image_info_by_ids(image_ids: str) -> list:
        """
        根据图片ID列表，获取图片信息列表
        :param image_ids: 图片ID列表，用逗号分隔
        :return: 图片信息列表
        """
        # 检查参数完整性
        if not image_ids:
            raise BasicException(status_code=StatusCode.BAD_REQUEST_ERROR.value, error_message="请完善参数")
        # 获取图片信息列表
        image_list: list = []
        for image_model in ImageMapper.get_info_by_ids(image_ids=image_ids):
            image_list.append(image_model.to_dict())
        return image_list
